package com.huajin.codetest.lock.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * ReentrantLock
 * 全限定类名：java.util.concurrent.locks.ReentrantLock.ReentrantLock()
 * JDK1.5
 *
 */
public class ReentrantLockSource {
	
	/**
	 * 同步器提供了所有实现机制
	 */
    private final Sync sync;
    
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 执行非公平tryLock
         * tryAcquire在子类中实现
         * 但两者都需要trylock方法的非公平尝试。
         */
        //@ReservedStackAccess
        final boolean nonfairTryAcquire(int acquires) {
        	//-- 获取当前线程
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        //@ReservedStackAccess
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }
    
    /**
     * 非公平锁的同步对象
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * 公平锁的同步对象
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        //@ReservedStackAccess
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }
    
    /**
     * 创建一个ReentrantLock实例
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLockSource() {
        sync = new NonfairSync();
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLockSource(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    
    /**
     * Acquires the lock.
     *
     * <p>Acquires the lock if it is not held by another thread and returns
     * immediately, setting the lock hold count to one.
     *
     * <p>If the current thread already holds the lock then the hold
     * count is incremented by one and the method returns immediately.
     *
     * <p>If the lock is held by another thread then the
     * current thread becomes disabled for thread scheduling
     * purposes and lies dormant until the lock has been acquired,
     * at which time the lock hold count is set to one.
     */
    public void lock() {
    	//-- 调用AQS的acquire()方法
        sync.acquire(1);
    }
    
    /**
     * Acquires the lock only if it is not held by another thread at the time
     * of invocation.
     *
     * <p>Acquires the lock if it is not held by another thread and
     * returns immediately with the value {@code true}, setting the
     * lock hold count to one. Even when this lock has been set to use a
     * fair ordering policy, a call to {@code tryLock()} <em>will</em>
     * immediately acquire the lock if it is available, whether or not
     * other threads are currently waiting for the lock.
     * This &quot;barging&quot; behavior can be useful in certain
     * circumstances, even though it breaks fairness. If you want to honor
     * the fairness setting for this lock, then use
     * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS)}
     * which is almost equivalent (it also detects interruption).
     *
     * <p>If the current thread already holds this lock then the hold
     * count is incremented by one and the method returns {@code true}.
     *
     * <p>If the lock is held by another thread then this method will return
     * immediately with the value {@code false}.
     *
     * @return {@code true} if the lock was free and was acquired by the
     *         current thread, or the lock was already held by the current
     *         thread; and {@code false} otherwise
     */
    public boolean tryLock() {
    	//-- 调用sync自己实现的nonfairTryAcquire()方法
        return sync.nonfairTryAcquire(1);
    }
    
    /**
     * Attempts to release this lock.
     * 
     * 尝试去方法锁
     *
     * <p>If the current thread is the holder of this lock then the hold
     * count is decremented.  If the hold count is now zero then the lock
     * is released.  If the current thread is not the holder of this
     * lock then {@link IllegalMonitorStateException} is thrown.
     *
     * @throws IllegalMonitorStateException if the current thread does not
     *         hold this lock
     */
    public void unlock() {
    	//-- 1、调用AQS的release()方法，arg参数为1
    	//-- 2、先判断AQS的tryRelease()方法，arg参数为1，但是AQS的tryRelease()方法并未实现，因此调用的是子类Sync的tryRelease()方法，releases参数为1
    	//-- 3、Sync的tryRelease()方法大致逻辑：判断当前线程是不是持有当前锁的线程，如果不是则抛出异常，如果是则AQS的状态原子值state减去1，
    	//--       如果重新计算后的AQS的状态原子值state为0，则将当前锁的持有线程设置为null，并释放锁标志为true，也要更新AQS的状态原子值state，最后返回释放锁标志true
    	//--       这里更新state值并不需要用CAS原子操作，因为只有一个线程会占用这个锁，不是这个线程都异常退出了
    	//--       如果重新计算后的AQS的状态原子值state不为0，则更新AQS的状态原子值state，最后返回释放锁标志false
    	//--4、如果3返回为false，则AQS的release()方法结束，返回false;
    	//--      如果3返回为true，则AQS的release()方法进入到条件判断中，获取到头节点，
    	//--      如果头结点不为null且头节点的等待状态不是初始化状态则调用AQS的unparkSuccessor()方法，如果存在后续节点，则唤醒节点的后续节点
    	//--      如果头节点为null或者且头节点的等待状态等于初始化状态则返回true
        sync.release(1);
    }

}
